﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MovieDbLib;
using MovieDbLib.Data;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace MovieHashesTool
{
  public partial class HashTool : Form
  {
    MovieDbHandler handler; 
    private Thread movieLoadingThread;

    public HashTool()
    {
      InitializeComponent();
      if (File.Exists("api_key.txt"))
      {
        handler = new MovieDbHandler(File.ReadAllText("api_key.txt"));
      }
      else
      {
        MessageBox.Show("Make sure you have your api key in a file called \"api_key.txt\" in the same folder as the application",
                        "No Api key found");
      }

      //use this for compiled releases
      //handler = new MovieDbHandler("");
    }


    private void cmdOpenDirectory_Click(object sender, EventArgs e)
    {
      if (openFolderForHash.ShowDialog() == DialogResult.OK)
      {
        TreeNode root = new TreeNode(openFolderForHash.SelectedPath);
        tvMovies.Nodes.Clear();
        tvMovies.Nodes.Add(root);

        movieLoadingThread = new Thread(new ParameterizedThreadStart(DoMovieSearch));
        movieLoadingThread.Priority = ThreadPriority.Lowest;
        movieLoadingThread.Start(root);
      }
    }

    /// <summary>
    /// Thread method to lookup all movies in the directory
    /// </summary>
    /// <param name="_root">Directory root</param>
    private void DoMovieSearch(object _root)
    {
      if (_root != null)
      {
        try
        {
          AddDirectoryNode(((TreeNode)_root).Text, ((TreeNode)_root));
          ExpandTreeViewItemThreadSafe(tvMovies, true);

        }
        catch (Exception ex)
        {
          MessageBox.Show(ex.ToString(), "Error loading movies");
        }
      }
    }


    /// <summary>
    /// Adds the directory to the treeview node
    /// </summary>
    /// <param name="_folder">The directory folder</param>
    /// <param name="_node">The treenode</param>
    private void AddDirectoryNode(String _folder, TreeNode _node)
    {
      foreach (String d in Directory.GetDirectories(_folder))
      {
        TreeNode node = new TreeNode();
        DirectoryInfo dirInfo = new DirectoryInfo(d);
        node.ImageIndex = 0;
        node.Text = dirInfo.Name;
        node.Tag = dirInfo;
        AddTreeNodeThreadSafe(_node, node);
        AddDirectoryNode(d, node);
      }

      foreach (String f in Directory.GetFiles(_folder))
      {
        FileInfo fileInfo = new FileInfo(f);

        if (MovieDbUtils.IsVideoFile(fileInfo))
        {
          TreeNode node = new TreeNode();
          node.Text = fileInfo.Name;
          node.Tag = fileInfo;

          HashMovieInfo info = new HashMovieInfo();
          info.MovieFile = fileInfo;

          String hash = MovieDbUtils.GetMovieHashString(f);
          info.MovieHash = hash;

          List<MovieDbMovie> movies = handler.SearchMovieByHash(hash);
          if (movies.Count == 1)
          {//the hash search produced a valid result
            info.MovieDbMovie = movies[0];
            Console.WriteLine("Found movie " + info.MovieDbMovie.MovieName + " from hash (" + fileInfo.Name + ")");
            node.ForeColor = Color.Green;
            node.Text += " (" + movies[0].MovieName + ")";
            node.ImageIndex = 1;
          }
          else
          {
            Console.WriteLine("Couldn't find movie from hash for file " + fileInfo.Name);
            node.ForeColor = Color.DarkRed;
            node.ImageIndex = 2;
          }
          node.Tag = info;
          AddTreeNodeThreadSafe(_node, node);
        }
      }
    }

    delegate void AddTreeNodeThreadSafeDelegate(TreeNode _lv, TreeNode _item);
    void AddTreeNodeThreadSafe(TreeNode _lv, TreeNode _item)
    {
      if (!InvokeRequired)
      {
        try
        {
          _lv.Nodes.Add(_item);
          tvMovies.ExpandAll();
        }
        catch (Exception ex)
        {
          Console.WriteLine(ex.ToString());
        }
      }
      else
        Invoke(new AddTreeNodeThreadSafeDelegate(AddTreeNodeThreadSafe), new object[] { _lv, _item });
    }

    delegate void ExpandTreeViewItemThreadSafeDelegate(TreeView _lv, bool _item);
    void ExpandTreeViewItemThreadSafe(TreeView _lv, bool _item)
    {
      if (!InvokeRequired)
      {
        try
        {
          _lv.ExpandAll();
        }
        catch (Exception ex)
        {
          Console.WriteLine(ex.ToString());
        }
      }
      else
        Invoke(new ExpandTreeViewItemThreadSafeDelegate(ExpandTreeViewItemThreadSafe), new object[] { _lv, _item });
    }

    private void lblMovieDbLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
    {
      String link = e.Link.LinkData.ToString();
      Process.Start(link);
    }

    private void tvMovies_AfterSelect(object sender, TreeViewEventArgs e)
    {
      if (tvMovies.SelectedNode != null && tvMovies.SelectedNode.Tag != null &&
         tvMovies.SelectedNode.Tag.GetType() == typeof(HashMovieInfo))
      {
        HashMovieInfo selectedMovie = tvMovies.SelectedNode.Tag as HashMovieInfo;
        txtHash.Text = selectedMovie.MovieHash;
        if (selectedMovie.MovieDbMovie != null)
        {
          txtMovieId.Text = selectedMovie.MovieDbMovie.Id.ToString();
          txtMovieName.Text = selectedMovie.MovieDbMovie.MovieName;
          txtImdbId.Text = selectedMovie.MovieDbMovie.ImdbId;
          txtMovieOverview.Text = selectedMovie.MovieDbMovie.Overview;
          txtMovieYear.Text = selectedMovie.MovieDbMovie.Released.ToShortDateString();

          lblMovieDbLink.Text = selectedMovie.MovieDbMovie.Url;
          lblMovieDbLink.Links.Clear();
          lblMovieDbLink.Links.Add(new LinkLabel.Link(0, selectedMovie.MovieDbMovie.Url.Length, selectedMovie.MovieDbMovie.Url));

          if (selectedMovie.MovieDbMovie.Backdrops.Count > 0)
          {
            if (selectedMovie.MovieDbMovie.Backdrops[0].Poster.IsLoaded ||
                selectedMovie.MovieDbMovie.Backdrops[0].Poster.LoadBanner())
            {
              pbBackdrop.Image = selectedMovie.MovieDbMovie.Backdrops[0].Poster.BannerImage;
            }
          }
          else
          {
            pbBackdrop.Image = null;
          }

          if (selectedMovie.MovieDbMovie.Posters.Count > 0)
          {
            if (selectedMovie.MovieDbMovie.Posters[0].Mid.IsLoaded ||
                selectedMovie.MovieDbMovie.Posters[0].Mid.LoadBanner())
            {
              pbPoster.Image = selectedMovie.MovieDbMovie.Posters[0].Mid.BannerImage;
            }
          }
          else
          {
            pbPoster.Image = null;
          }
        }
        else
        {
          ClearTextBoxes();
          txtHash.Text = selectedMovie.MovieHash;
          txtMovieId.Text = "Unknown";
          txtMovieName.Text = "Couldn't identify Movie";
        }
      }
      else
      {
        ClearTextBoxes();
      }
    }

    private void ClearTextBoxes()
    {
      txtHash.Text = "";
      txtMovieId.Text = "";
      txtMovieName.Text = "";
      txtImdbId.Text = "";
      txtMovieOverview.Text = "";
      txtMovieYear.Text = "";

      pbPoster.Image = null;
      pbBackdrop.Image = null;
    }
  }
}
